﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace SIEGEwebapp
{
    public partial class wfPlanProd : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void APIErrorCheck(IntPtr pEnv, int nErr)
        {
            if (nErr > 0)
            {
                StringBuilder cMessage = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);
                lindo.LSgetErrorMessage(pEnv, nErr, cMessage);
                this.lblMsg.Text = cMessage.ToString();
            }
        }

        protected void btnCargarDatos_Click(object sender, EventArgs e)
        {
            string InfCon;
            InfCon = @"Data Source = MARY\SQLExpress2008; Initial Catalog = AplicacionWeb; Integrated Security = True";
            SqlConnection oCon;
            oCon = new SqlConnection(InfCon);


            SqlCommand oCom;
            string SelectSQL = "SELECT * FROM PlanProd";
            oCom = new SqlCommand(SelectSQL, oCon);

            SqlDataReader oLector;
            oCon.Open();
            oLector = oCom.ExecuteReader();
            while (oLector.Read())
            {
                int Trimestre = (int)oLector["Trimestre"];
                double Demanda = (double)oLector["Demanda"];
                double CostoProd = double.Parse(oLector["CostoProd"].ToString());
                double CostoInv = double.Parse(oLector["CostoInv"].ToString());
                switch (Trimestre)
                {
                    case 1:
                        txtDemanda1.Text = Demanda.ToString();
                        txtCostoProd1.Text = CostoProd.ToString();
                        txtCostoInv1.Text = CostoInv.ToString();
                        break;
                    case 2:
                        txtDemanda2.Text = Demanda.ToString();
                        txtCostoProd2.Text = CostoProd.ToString();
                        txtCostoInv2.Text = CostoInv.ToString();
                        break;
                    case 3:
                        txtDemanda3.Text = Demanda.ToString();
                        txtCostoProd3.Text = CostoProd.ToString();
                        txtCostoInv3.Text = CostoInv.ToString();
                        break;
                    case 4:
                        txtDemanda4.Text = Demanda.ToString();
                        txtCostoProd4.Text = CostoProd.ToString();
                        txtCostoInv4.Text = CostoInv.ToString();
                        break;
                }
            }
            oLector.Close();

            SelectSQL = "SELECT * FROM ConfProductos";
            oCom.CommandText = SelectSQL;
            oLector = oCom.ExecuteReader();
            oLector.Read();
            txtInventarioInicial.Text = oLector["InvInicial"].ToString();
            txtCapMax.Text = oLector["CapacidadMax"].ToString();
            oLector.Close();
            oCon.Close();
        }

        protected void btnOptimizar_Click(object sender, EventArgs e)
        {
            int nErrorCode = lindo.LSERR_NO_ERROR;

            /* Número de restricciones */
            int nCons = 4;

            /* Número de variables de decisión */
            int nVars = 8;

            /* Se declara una variable que nos va a permitir comunicarnos con LINDO */
            IntPtr pEnv = (IntPtr)0;

            /* Se declara una variable que nos va a permitir tratar con el modelo */
            IntPtr pModel = (IntPtr)0;

            int nSolStatus = lindo.LS_STATUS_UNKNOWN;

            StringBuilder LicenseKey = new StringBuilder(lindo.LS_MAX_ERROR_MESSAGE_LENGTH);

            /* >>> PASO 1 <<< Lograr la comunicación con LINDO */
            nErrorCode = lindo.LSloadLicenseString(@"C:\Lindoapi\license\lndapi90.lic", LicenseKey);
            APIErrorCheck(pEnv, nErrorCode);

            pEnv = lindo.LScreateEnv(ref nErrorCode, LicenseKey.ToString());
            if (nErrorCode == lindo.LSERR_NO_VALID_LICENSE)
            {
                lblMsg.Text = "¡LICENCIA NO VÁLIDA!\n";
                return;
            }
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 2 <<< Crear el modelo */
            pModel = lindo.LScreateModel(pEnv, ref nErrorCode);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 3 <<< Especificar el modelo */

            /* El tipo de optimización */
            int nDir = lindo.LS_MIN;

            /* El término constante de la función objetivo */
            double dObjConst = 0;

            /* Los coeficientes de la función objetivo */
            double[] adC = new double[nVars];
            adC[0] = double.Parse(txtCostoProd1.Text);
            adC[1] = double.Parse(txtCostoProd2.Text);
            adC[2] = double.Parse(txtCostoProd3.Text);
            adC[3] = double.Parse(txtCostoProd4.Text);
            adC[4] = double.Parse(txtCostoInv1.Text);
            adC[5] = double.Parse(txtCostoInv2.Text);
            adC[6] = double.Parse(txtCostoInv3.Text);
            adC[7] = double.Parse(txtCostoInv4.Text);

            /* El lado derecho de las restricciones */
            double[] adB = new double[nCons];
            adB[0] = double.Parse(txtDemanda1.Text) - double.Parse(txtInventarioInicial.Text);
            adB[1] = double.Parse(txtDemanda2.Text);
            adB[2] = double.Parse(txtDemanda3.Text);
            adB[3] = double.Parse(txtDemanda4.Text);

            /* Los tipos de restricciones */
            string acConTypes = "GGGG";


            /* El número de elementos que NO son cero en la matriz de restricciones */
            int nNZ = 11;

            /* La posición del primer elemento NO cero de cada columna */
            int[] anBegCol = new int[] { 0, 1, 2, 3, 4, 6, 8, 10, nNZ };

            /* La longitud de cada columna en cuanto a los elementos que NO son cero */
            int[] pnLenCol = new int[] { 1, 1, 1, 1, 2, 2, 2, 1 };

            /* Los coeficientes que NO son cero por columna */
            double[] adA = new double[] { 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1 };

            /* La posición por fila de los elementos que NO son cero */
            int[] anRowX = new int[] { 0, 1, 2, 3, 0, 1, 1, 2, 2, 3, 3 };

            /* Cotas inferiores y superiores de cada variable */
            double[] pdLower = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 };
            double CapacidadMax = double.Parse(txtCapMax.Text);
            double[] pdUpper = new double[] { CapacidadMax, CapacidadMax, CapacidadMax, CapacidadMax,
                                              lindo.LS_INFINITY, lindo.LS_INFINITY,
                                              lindo.LS_INFINITY, lindo.LS_INFINITY };

            /* Nombres de variables y restricciones */
            string[] varnames = new string[] { "X1", "X2", "X3", "X4", "Y1", "Y2", "Y3", "Y4" };
            string[] connames = new string[] { "R1", "R2", "R3", "R4" };

            /* Cargamos el modelo */
            nErrorCode = lindo.LSloadLPData(pModel, nCons, nVars, nDir,
                dObjConst, adC, adB, acConTypes, nNZ, anBegCol,
                pnLenCol, adA, anRowX, pdLower, pdUpper);
            APIErrorCheck(pEnv, nErrorCode);

            nErrorCode = lindo.LSloadNameData(pModel, "Plan de Producción", null, null, null,
            null, connames, varnames, null);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 4 <<< Correr el modelo matemático */
            nErrorCode = lindo.LSoptimize(pModel, lindo.LS_METHOD_PSIMPLEX, ref nSolStatus);
            APIErrorCheck(pEnv, nErrorCode);

            /* >>> PASO 5 <<< Tomar la salida de la optimización */

            /* Se toma el valor de la función objetivo */
            double dObj = 0;
            nErrorCode = lindo.LSgetInfo(pModel, lindo.LS_DINFO_POBJ, ref dObj);
            APIErrorCheck(pEnv, nErrorCode);
            // Se atrapa el valor de la función objetivo
            this.txtCostosTotales.Text = dObj.ToString();

            /* Se toman los valores de las variables */
            double[] adX = new double[nVars];
            nErrorCode = lindo.LSgetPrimalSolution(pModel, adX);
            APIErrorCheck(pEnv, nErrorCode);

            txtUnidadesFabricar1.Text = adX[0].ToString();
            txtUnidadesFabricar2.Text = adX[1].ToString();
            txtUnidadesFabricar3.Text = adX[2].ToString();
            txtUnidadesFabricar4.Text = adX[3].ToString();

            txtUnidadesAlmacenar1.Text = adX[4].ToString();
            txtUnidadesAlmacenar2.Text = adX[5].ToString();
            txtUnidadesAlmacenar3.Text = adX[6].ToString();
            txtUnidadesAlmacenar4.Text = adX[7].ToString();

            /* >>> PASO 6 <<< Borramos el modelo de LINDO y cortamos la comunicación con el SOLVER */
            nErrorCode = lindo.LSdeleteModel(ref pModel);
            nErrorCode = lindo.LSdeleteEnv(ref pEnv);
        }
    }

}